import { getType } from 'mime'
import store from '../store'
import tinymce from 'tinymce/tinymce'
import { v4 as uuid } from 'uuid'
import { cloneDeep, difference } from 'lodash'
import { contentPrototypes, defaultDataTypes, isListTitle, contentTypes } from '@/constants/structure'
import { allContentTypes, groupBlockTypes, isAnnexByType, pagePrototypes, spanTypes } from '@/constants/structure'
import { parsePageData } from './parse/parse'
import { Message } from 'element-ui'
import { StdBlock } from './parse/block'
import { save } from '@/api'
import { getStrData2Save } from './save'

export function getRange(sourceType) {
  const editor = tinymce.activeEditor
  const rng = editor.selection.getRng()
  const getNode = (n) => (n.nodeType === 3 ? editor.dom.getParent(n, '[data-type]') : n)
  const { startContainer, endContainer, startOffset, endOffset } = rng
  const startNode = getNode(startContainer)
  const endNode = getNode(endContainer)
  const startContainerId = startNode?.dataset?.id
  const endContainerId = endNode?.dataset?.id
  const doc = rng.cloneContents()
  const groupId = uuid()
  let data
  if (startContainerId === endContainerId) {
    const figureDom = editor.dom.getParent(startNode, 'div[data-type="figure"]')
    const formulaDom = editor.dom.getParent(startNode, 'div.formula')
    const tableDom = editor.dom.getParent(startNode, 'table[data-type="table"]')
    const parentDom = figureDom || formulaDom || tableDom
    if (parentDom) {
      // 图结构化、表格结构化、公式结构化的收藏
      data = parsePageData(editor.dom.createFragment(`<div>${parentDom.outerHTML}</div>`))?.map((i) => {
        if (!i.blockType && sourceType) {
          i.setBlockType(sourceType)
        }
        if (!i.groupId) {
          i.setGroupId(groupId)
        }
        return i
      })
    } else if (startContainer.nodeType === 3) {
      const content = startContainer.textContent.substring(startOffset, endOffset)
      data = [
        new StdBlock({
          blockType: sourceType,
          groupId,
          textData: { contentList: [{ content, fullContent: content }] }
        })
      ]
    } else if (startContainer.nodeName === 'P') {
      data = parsePageData(editor.dom.createFragment(`<div>${startContainer.outerHTML}</div>`))
    }
  } else {
    data = parsePageData(doc)?.map((i) => {
      if (!i.blockType && sourceType) {
        i.setBlockType(sourceType)
      }
      if (!i.groupId) {
        i.setGroupId(groupId)
      }
      return i
    })
  }

  return {
    startContainerId,
    endContainerId,
    docContent: JSON.stringify(data || []),
    startIndex: startOffset,
    endIndex: endOffset
  }
}

export function getCooperatorId() {
  return store.state.xmleditor.currentUserInfo?.userId || null
}

export function editable(dataset) {
  return store.state.xmleditor.editableIds.includes(dataset.pageId)
}

/** 新增或修改附录类型时，显示的内容会相应变化 */
export function getAnnexLabel(data) {
  const { annexNumber, pageType, annexName } = data
  return `- 附录${annexNumber}(${pageType === 'normativeAnnex' ? '规' : '资'}) ${annexName}`
}

export function scrollTo(outerEl, innerEl, behavior = 'instant') {
  const parent = tinymce.activeEditor.getWin()
  const pageZoom = store.state.xmleditor.pageZoom
  const topOffset = outerEl?.offsetTop ? 104 : 10
  parent.scrollTo({
    top: ((outerEl?.offsetTop || 0) + (innerEl?.offsetTop || 0) - topOffset) * pageZoom,
    behavior
  })
}

export function scrollPageByData(data) {
  if (data.dataType === 'figure' || data.dataType === 'table' || data.trigger === 'hash') {
    const doc = tinymce.activeEditor.getDoc()
    let el = doc.querySelector(`[data-block-id="${data.blockId}"]`)
    let offset = 68
    if (!el) {
      el = doc.querySelector(`[data-id="${data.blockId}"]`) // 列项
      offset += 200
    }
    const outEl = tinymce.activeEditor.dom.getParent(el, '.page-sheet')
    const parent = tinymce.activeEditor.getWin()
    if (data.trigger === 'hash') {
      parent.scrollTo({ top: (outEl?.offsetTop || 0) + (el?.offsetTop || 0) - offset, behavior: 'smooth' })
      return
    }
    parent.scrollTo({ top: (outEl?.offsetTop || 0) + (el?.offsetTop || 0) - 10 })
    return
  }
  if (data.key === 0 || data.key === 500 || data.key === 600) return
  const doc = tinymce.activeEditor.getDoc()
  const page = doc.querySelector(`[data-page-id="${data.dataId}"]`)
  const block = doc.querySelector(`[data-block-id="${data.dataId || data.blockId}"]`)
  const dom = doc.querySelector(`[data-id="${data.dataId}"]`)
  let el = page || dom || block

  if (allContentTypes.includes(data.dataType)) {
    el = tinymce.activeEditor.dom.getParent(el, '.page-sheet')
  }

  let outEl = null
  if (!tinymce.activeEditor.dom.is(el, '.page-sheet') && data.dataType) {
    if ([...allContentTypes, ...spanTypes].includes(data.dataType) || /item[1-4]/g.test(data.dataType)) {
      outEl = tinymce.activeEditor.dom.getParent(el, '.page-sheet')
    }
  }
  scrollTo(outEl, el)
}

export function sleep(time = 0) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}

export function assignPageFields(page) {
  if (isAnnexByType(page.pageType)) {
    const getContent = (t, field) => page.blockList.find((i) => i.dataType === t).textData.contentList[0][field] || ''
    const annexNumber = getContent('annex_number', 'contentNumber')
    const annexNumberText = getContent('annex_number', 'fullContent')
    const annexTypeText = getContent('annex_type_name', 'fullContent')
    const annexName = getContent('annex_title', 'fullContent')
    const annexNameEn = page.blockList.find((i) => i.dataType === 'annex_title' && i.textData.dataLang === 'en')
      ?.textData?.contentList?.[0]?.fullContent
    let title = annexNumberText + annexTypeText + '&nbsp;&nbsp;&nbsp;&nbsp;' + annexName
    if (store.getters.languageType === 'both') {
      const annexTypeMap = {
        normativeAnnex: { zh: '规范性附录', en: 'Normative' },
        informativeAnnex: { zh: '资料性附录', en: 'Informative' }
      }
      const aT = annexTypeMap[page.pageType]
      title = `附录${annexNumber}(Annex ${annexNumber})(${aT.zh})(${aT.en})${annexName}(${annexNameEn})`
    }
    const titleZh = `附录${annexNumber}${annexTypeText}`
    const titleEn = `Annex ${annexNumber}`
    return { annexNumber, annexNumberText, annexTypeText, annexName, annexNameEn, title, titleZh, titleEn, ...page }
  }
  const proto = pagePrototypes.find((i) => i.pageType === page.pageType)
  let title = proto.label
  if (store.getters.languageType === 'both') {
    title += `(${proto.labelEn})`
  }
  const titleZh = proto.label
  const titleEn = `${proto.labelEn}`
  return { title, titleZh, titleEn, disabled: proto.disabled, ...page }
}
function getTitle(item) {
  if (defaultDataTypes.includes(item.dataType)) {
    const { label, labelEn } = contentPrototypes.find((i) => i.dataType === item.dataType)
    return store.getters.languageType === 'both' ? `${label}(${labelEn})` : label
  }
  return item?.textData?.contentList?.map((i) => i?.fullContent).join('')
}
function getTitleZh(item) {
  if (defaultDataTypes.includes(item.dataType)) {
    return contentPrototypes.find((i) => i.dataType === item.dataType).label
  }
  return item?.textData?.contentList?.map((i) => i?.content).join('')
}
function getTitleEn(item) {
  if (defaultDataTypes.includes(item.dataType)) {
    return contentPrototypes.find((i) => i.dataType === item.dataType).labelEn
  }
  return item?.textData?.contentList?.map((i) => i?.contentEn).join('')
}

export function assignContentBlockFields(block) {
  block.children?.forEach((item) => {
    item.title = getTitle(item)
  })
  block.children = block.children?.map(assignContentBlockFields)

  return {
    title: getTitle(block),
    titleZh: getTitleZh(block),
    titleEn: getTitleEn(block),
    ...block
  }
}

export function assignContentPageFields(page) {
  const block = page.blockList.find((x) => allContentTypes.includes(x.dataType))

  return {
    dataType: block.dataType, // 正文页面类型，如 scope
    title: block?.textData?.contentList?.map((i) => i?.fullContent).join(''),
    ...page
  }
}

function getFirstTextNode(el) {
  for (let i = 0; i < el.childNodes.length; i++) {
    const child = el.childNodes[i]
    if (child.nodeType === 3) {
      return child
    }
  }
  return null
}

export function scrollAndSelectRange(item) {
  const doc = tinymce.activeEditor.getDoc()
  const el = doc.querySelector(`[data-id="${item.startContainerId}"]`)

  // 滚动屏幕到选中节点
  const outEl = tinymce.activeEditor.dom.getParent(el, '.page-sheet')
  if (!el) return
  scrollTo(outEl, el)

  // 创建选区
  const rng = tinymce.DOM.createRng()
  const elFirstChild = getFirstTextNode(el)
  if (!el) {
    console.error('---error el first child---')
    return
  }
  rng.setStart(elFirstChild, item.startIndex)
  const endEl = doc.querySelector(`[data-id="${item.endContainerId}"]`)
  const endElFirstChild = getFirstTextNode(endEl)
  if (!endElFirstChild) {
    console.error('---error endEl first child---')
    return
  }
  rng.setEnd(endElFirstChild, item.endIndex)

  // 设置选中
  tinymce.activeEditor.selection.setRng(rng)
}

export const parseFileName = (res) => {
  const disposition = res.headers['content-disposition']
  return disposition ? decodeURIComponent(disposition.substring(20)) : ''
}

export const exportFile = (res) => {
  const type = getType(res.headers['content-disposition'])
  const fileName = parseFileName(res)
  const blob = new Blob([res.data], { type })
  const filename = fileName
  if (typeof window.navigator.msSaveBlob !== 'undefined') {
    window.navigator.msSaveBlob(blob, filename)
  } else {
    var blobURL = window.URL.createObjectURL(blob)
    // 创建隐藏<a>标签进行下载
    var tempLink = document.createElement('a')
    tempLink.style.display = 'none'
    tempLink.href = blobURL
    tempLink.setAttribute('download', filename)
    if (typeof tempLink.download === 'undefined') {
      tempLink.setAttribute('target', '_blank')
    }
    document.body.appendChild(tempLink)
    tempLink.click()
    document.body.removeChild(tempLink) // 移除dom元素
    window.URL.revokeObjectURL(blobURL) // 释放bolb内存
  }
}
export const previewFile = (res) => {
  const open = window.open()
  open.location = window.URL.createObjectURL(res.data)
}

export function getComponentName(item) {
  switch (item.dataType) {
    case 'block_group': // 虚拟的块级元素，用于插入内容，不可修改
      return 'BlockGroup'
    case 'table':
      return 'EditorTable'
    case 'figure':
      return 'EditorFigure'
    case 'formula':
      return 'EditorFormula'
    case 'abbreviation':
      return 'EditorAbbreviation'
    case 'terms':
      return 'TermBlock'
    case 'example':
      return 'Example'
    case 'naked_figure':
      return 'NakedFigure'
    case 'item_note':
      return 'ItemNote'
    case 'endline':
      return 'Endline'
    case 'item_list':
      return 'ItemList'
    // case 'variable_img':
    //   return 'ImageBlock'
    default:
      return 'Paragraph'
  }
}

export function groupBlockList(list) {
  let blockArr = []
  let lastGroupId = ''

  return list.reduce((prev, cur, idx, arr) => {
    if (idx === 0) {
      lastGroupId = cur.groupId
    }
    // 当前是块
    if (groupBlockTypes.includes(cur.blockType)) {
      // 和前一个内容属于同一个块
      if (cur.groupId === lastGroupId) {
        blockArr.push(cur)
        // 当前块是最后的内容
        if (idx === arr.length - 1) {
          prev.push({ dataType: 'block_group', blockId: uuid(), list: cloneDeep(blockArr) })
          blockArr = null
        }
      } else {
        // 和前一个不属于相同块
        if (blockArr.length) {
          prev.push({ dataType: 'block_group', blockId: uuid(), list: cloneDeep(blockArr) })
        }
        blockArr = [cur]
        // 当前块是最后的内容
        if (idx === arr.length - 1) {
          prev.push({ dataType: 'block_group', blockId: uuid(), list: cloneDeep(blockArr) })
          blockArr = null
        }
      }
      lastGroupId = cur.groupId
    } else {
      // 当前不是块
      // 前一个是块
      if (blockArr.length) {
        prev.push({ dataType: 'block_group', blockId: uuid(), list: cloneDeep(blockArr) })
        blockArr = []
      }
      prev.push(cur)
    }
    return prev
  }, [])
}

/** 获取页面类型
 * 1. 附录页单独处理
 * 2. 正文页面除 chapter后端返回 content，其他都是正常的
 * 3. 空白页需要根据前面的正文页决定
 */
export function getPageType(pageNode) {
  if (pageNode?.dataset?.annexType) {
    return pageNode?.dataset?.annexType
  }
  const contentPageType = pageNode?.dataset?.contentPageType
  if (contentPageType) {
    if (contentPageType === 'blank_page') {
      return getPageType(tinymce.activeEditor.dom.getPrev(pageNode, '.page-sheet[data-content-page-type]'))
    }
    return contentPageType
  }

  return pageNode?.dataset?.pageType
}

/**
 * 获取页面名字
 * 1. 如果是规范的名字可以直接返回
 * 2. 如果是自定义的正文页面（chapter和插入的空白页两种情况），找正文页的章标题
 */
function getPageTypeName(pageType, currentNode) {
  const { pageTypeMap } = store.getters.ruleExpressions
  if (pageTypeMap[pageType]) {
    return pageTypeMap[pageType]
  }

  if (pageType === 'chapter') {
    let chapterTitle = currentNode.querySelector('[data-type="chapter"]')?.innerText
    while (currentNode && !chapterTitle) {
      currentNode = tinymce.activeEditor.dom.getPrev(currentNode, '.page-sheet[data-content-page-type]')
      chapterTitle = currentNode.querySelector('[data-type="chapter"]')?.innerText
      console.debug('---getPageTypeName: while loop---')
    }
    return chapterTitle
  }

  return '==Error=='
}

// insertType: 1. abbreviation, 2. block, 3. collect, 4. department, 5. terms,
//             6. pageBreak, 7. table, 8. figure, 9. formula, 10. chart
//             11. subscript, 12. superscript, 13. inline_figure, 14. inline_formula
//             15. docContent在新的一行内插入
export function checkBeforeInsert(insertType = '', silent = false) {
  const currentNode = tinymce.activeEditor.selection.getNode()
  if (currentNode.contentEditable === false || currentNode.contentEditable === 'false') {
    !silent && Message.warning({ message: '当前位置不能插入该内容，请将光标置于正确的位置', showClose: true })
    return false
  }
  // 如果光标在列项中,插入时报错,提示:列项仅支持纯文本, 'department', 'refdoc', 'refchapter'
  const inItemlist = tinymce.activeEditor.dom.getParent(currentNode, '[data-type="item_list"]')
  const inline = ['subscript', 'superscript', 'sub', 'sup', 'charmap', 'inline_figure']
  if (inItemlist && ![...inline, 'item_list', 'department', 'refdoc', 'refchapter'].includes(insertType)) {
    !silent && Message.warning({ message: '列项仅支持纯文本', showClose: true })
    return false
  }
  // 图片或表格中不能插入公式
  if (tinymce.activeEditor.dom.getParent(currentNode, '[data-type="figure"]') && insertType === 'formula') {
    !silent && Message.warning({ message: '图片中不能插入公式', showClose: true })
    return false
  }
  if (tinymce.activeEditor.dom.getParent(currentNode, 'table') && insertType === 'formula') {
    !silent && Message.warning({ message: '表格中请插入行内公式', showClose: true })
    return false
  }
  if (tinymce.activeEditor.dom.getParent(currentNode, '[data-type="figure"]') && insertType === 'figure') {
    !silent && Message.warning({ message: '图片中不能插入图片', showClose: true })
    return false
  }
  if (tinymce.activeEditor.dom.getParent(currentNode, 'table') && insertType === 'figure') {
    !silent && Message.warning({ message: '表格中请插入行内图片', showClose: true })
    return false
  }
  const currentPage = tinymce.activeEditor.dom.getParent(currentNode, '.page-sheet')
  if (!currentPage) {
    !silent && Message.warning({ message: '当前位置不能插入该内容，请将光标置于正确的位置', showClose: true })
    return false
  }

  const { ruleMap, contentTypeMap } = store.getters.ruleExpressions
  if (ruleMap[insertType] || insertType === 'pageBreak') {
    /**
     * 未处理："example" "item_note", "figure_note", "table_note", "item_footnote", "figure_footnote", "table_footnote"
     * 已处理："formula" "figure" "table" "item"
     * 不做处理："endline"  "text"
     */
    let pageType = getPageType(currentPage)
    if (!pageType) {
      !silent && Message.error('错误的数据')
      return false
    }
    // console.debug('---check before insert---', insertType, pageType, ruleMap[insertType])
    if (insertType !== 'pageBreak' && !ruleMap[insertType].includes(pageType)) {
      const pageTypeName = getPageTypeName(pageType, currentPage)
      const contentTypeName = contentTypeMap[insertType]
      !silent && Message.warning(`按照当前最新规范，【${pageTypeName}】页面内不能添加【${contentTypeName}】`)
      return false
    }
  }

  if (getPageType(currentPage) === 'terms_definitions') {
    // 普通文档
    if (store.state.xmleditor.filePropertyName !== 'TERM') {
      if (insertType != 'terms') {
        !silent && Message.warning('非术语文档的术语和定义页面仅能插入术语')
        return false
      }
    }
  }

  // 判断是否在术语页面
  if (insertType === 'terms') {
    if (store.getters.isTermDoc) {
      !silent && Message.warning('术语文档不能插入术语')
      return false
    }

    if (getPageType(currentPage) !== 'terms_definitions') {
      !silent && Message.warning('请在术语和定义页面插入')
      return false
    }
  }
  // 插入缩略语
  if (getPageType(currentPage) === 'symbols_abbreviation') {
    if (insertType != 'abbreviation') {
      !silent && Message.warning('缩略语页面仅能插入缩略语')
      return false
    }
  }
  if (insertType === 'abbreviation') {
    if (store.getters.isAbbrDoc) {
      !silent && Message.warning('缩略语文档不能插入缩略语')
      return false
    }

    if (getPageType(currentPage) !== 'symbols_abbreviation') {
      !silent && Message.warning('请在缩略语页面插入')
      return false
    }
  }

  const { pageType, contentPageType } = currentPage?.dataset
  if (insertType === 'pageBreak' && !allContentTypes.includes(contentPageType || pageType)) {
    !silent && Message.warning('当前页面不能进行分页!')
    return false
  }
  return true
}

export function getBaseUrl() {
  switch (store.getters.editContentType) {
    case 'template':
      return '/editor/documentTemplateInfo' // 1. 模板
    case 'collect':
      return '/editor/documentCollectInfo' // 2.1. 个人收藏
    case 'block':
      return '/editor/documentBlockInfo' // 2.2. 结构化内容块
    default:
      return '/editor/documentInfo' // 3. 文档
  }
}

/** 根据不同的入口和文档类型返回不同的编辑器参数，通过menu, plugins, toolbar显示不同的界面 */
export function getEditorParams() {
  const refPlugins = 'refChapter refdoc '
  const filePlugins = 'docSave docExport docCompare docPreview'
  const insertPlugins = 'block collect term abbreviation department docContent variable'
  const toolsPlugins = 'collaborate docCheck'
  const menuPlugins = `${filePlugins} ${refPlugins} ${insertPlugins} ${toolsPlugins} `
  const formatPlugins = '' // fontName fontSize textColor fontBold fontItalic fontUnderline
  const s1 = 'itemlist itemlistEn table image kityformula charmap chart example exampleEn '
  const s2 = 'itemnote itemnoteEn tablenote tablenoteEn figurenote figurenoteEn footnote footnoteEn '

  // 不同的editContentType
  let toolbarPlugins = s1 + s2 // 结构块或收藏：-
  if (this.$route.query.editContentType === 'document') {
    toolbarPlugins = 'chapter ' + s1 + 'pageBreak docRevLine ' + s2 + 'comment' // 文档:   pageBreak, chapter, comment, docRevLine
  } else if (this.$route.query.editContentType === 'template') {
    toolbarPlugins = 'chapter ' + s1 + 'pageBreak ' + s2 // 模板:   pageBreak, chapter
  }

  // 不同的entry入口进入后的页面显示不同的菜单和工具栏
  // 1. entry: flow，在制订或修订流程中，编辑器的只读模式：预览、导出、搜索、批注、收藏、关键词
  // 2. entry: preview，在搜索结果、体系视图或文档列表中，编辑器的只读模式：预览、导出、搜索、收藏、查看关键词
  const entry = this.entry || this.$route.query.entry || ''
  let menu = {
    file: { title: 'File', items: filePlugins },
    reference: { title: 'Reference', items: refPlugins },
    insert: { title: 'Insert', items: insertPlugins },
    tools: { title: 'Tools', items: toolsPlugins }
  }
  let plugins = `${menuPlugins} ${formatPlugins} paraLang pageContextmenu irremovable ${toolbarPlugins} link fullscreen searchreplace lists noneditable `
  let toolbar = `undo redo ${formatPlugins} subscript superscript paraLang ${toolbarPlugins} searchreplace fullscreen`

  if (entry === 'flow' || entry === 'preview' || entry === 'termpreview') {
    menu = {
      file: { title: 'File', items: 'docExport docPreview' },
      insert: { title: 'Insert', items: '' }
    }
  }
  if (entry === 'flow') {
    plugins = 'docExport docPreview pageContextmenu irremovable comment fullscreen searchreplace noneditable'
    toolbar = 'comment searchreplace fullscreen'
  }

  // 当是只读模式时，即 tinymce.activeEditor.mode.set('readonly')，plugin和toolbar设置了值无效
  if (entry === 'preview' || entry === 'htmlpreview' || entry === 'termpreview') {
    plugins = ''
    toolbar = ''
  }

  if (this.$route.query.editContentType !== 'document') {
    // document template 可以插入，collect block 不可以嵌套插入
    const insertItems = this.$route.query.editContentType === 'template' ? insertPlugins : ''
    menu = {
      file: { title: 'File', items: 'docSave' },
      reference: { title: 'Reference', items: refPlugins },
      insert: { title: 'Insert', items: insertItems }
    }
  }

  return { menu, plugins, toolbar }
}

/** 对关键词进行高亮处理 */
function highlightWord(editor, node, lastIndex, len) {
  const rng = tinymce.DOM.createRng()
  rng.setStart(node.firstChild, lastIndex)
  rng.setEnd(node.firstChild, lastIndex + len)
  editor.selection.setRng(rng)
  editor.selection.setContent('<mark>' + editor.selection.getContent() + '</mark>')
}

/** 处理全文搜索带过来的关键字 */
export function handleKeyword(editor) {
  if (store.state.xmleditor.editorConfig.keyword) {
    const k = store.state.xmleditor.editorConfig.keyword
    const nodeList = [...editor.getDoc()?.querySelectorAll('*')]
    for (const node of nodeList) {
      const nodeType = node?.firstChild?.nodeType
      const textContent = node?.firstChild?.textContent
      if (nodeType === 3 && new RegExp(k, 'g').test(textContent)) {
        let lastIndex = textContent.length - 1
        while (lastIndex > -1) {
          lastIndex = textContent.lastIndexOf(k, lastIndex)
          if (lastIndex === -1) break
          highlightWord(editor, node, lastIndex, k.length)
          lastIndex -= k.length
        }
      }
    }
  }
}

export function getPageById(pageId) {
  return tinymce.activeEditor.dom.select('#tinymce>.page-wrapper .page-sheet[data-page-id=' + pageId + ']')
}
export function getBlockById(blockId) {
  const block = tinymce.activeEditor.dom.select('#tinymce>.page-wrapper [data-block-id=' + blockId + ']')
  const block2 = tinymce.activeEditor.dom.select('#tinymce>.page-wrapper [data-id=' + blockId + ']')
  return block || block2
}
export function getPageByBlockId(blockId) {
  return tinymce.activeEditor.dom.getParent(getBlockById(blockId)?.[0], '.page-sheet')
}

export function getContentListById(pageList, id) {
  for (const page of pageList) {
    for (const block of page.blockList) {
      // 图注或图脚注
      if (block.dataType === 'figure' && block?.figureData?.noteList?.length > 0) {
        for (const note of block.figureData.noteList) {
          if (note?.textData?.dataId === id) {
            let list = cloneDeep(note?.textData?.contentList)
            list.splice(0, 1)
            return list
          }
        }
      }
      // 列项
      if (block.dataType === 'item_list' && block?.bulletData?.bulletList?.length > 0) {
        for (const note of block?.bulletData?.bulletList) {
          if (note?.textData?.dataId === id) {
            let list = cloneDeep(note?.textData?.contentList)
            list.splice(0, 1)
            return list
          }
        }
      }

      if (block?.textData?.dataId === id) {
        return block?.textData?.contentList
      }
    }
  }
}

// 日期格式化
export const dateFormat = (str = '') => {
  const reg = /^(\d{4}-\d{2}-\d{2})/
  if (reg.test(str)) {
    const [_, d] = str.match(reg)
    return d
  }
  return ''
}

export function emit(command, data) {
  const _this = store.state.xmleditor.editorRef
  if (!_this) {
    console.error('---editor ref error---')
  }
  _this.$emit(command, data)
}

function swap(list, indexA, indexB) {
  const itemA = cloneDeep(list[indexA])
  const itemB = cloneDeep(list[indexB])
  list.splice(indexA, 1, itemB)
  list.splice(indexB, 1, itemA)
}
export function moveup(list, idx) {
  swap(list, idx - 1, idx)
}
export function movedown(list, idx) {
  swap(list, idx, idx + 1)
}
export function remove(list, idx) {
  list.splice(idx, 1)
}

export function getPageSheetNode(editor) {
  return editor.dom.getParent(editor.selection.getNode(), '.page-sheet')
}

export function getSelectionNode(editor) {
  const selectionNode = editor.selection.getNode()
  return editor.dom.is(selectionNode, 'p') ? selectionNode : editor.dom.getParent(selectionNode, 'p')
}
export function getLinkUrl(filePath) {
  if (!filePath) return ''
  const origin = window.location.origin
  const apiPath = '/prod-api/editor/file/preview/'
  return origin + apiPath + filePath
}
export function findDocNodes(winDocument, blockIds) {
  const result = []
  const addedBlockIds = []
  const blockTypes = ['paragraph', 'figure', 'formula', 'item_list', 'table']
  function getNode(blockId) {
    const node = winDocument.querySelector(`[data-block-id="${blockId}"`)
    const checkbox = node.querySelector('[data-iframe-checkbox]')
    tinymce.activeEditor.dom.remove(checkbox)
    return node
  }

  function getNextNodes(node, endTypes = []) {
    let nextNode = node.nextElementSibling
    while(nextNode) {
      if(endTypes.includes(nextNode.dataset.type)) {
        nextNode = null
      } else {
        addedBlockIds.push(nextNode.dataset.blockId)
        result.push(nextNode)
        nextNode = nextNode.nextElementSibling
      }
    }
  }

  for (const blockId of blockIds) {
    const node = getNode(blockId)
    // 1. 如果是普通段落、表格、图片、公式、列项，
    // 先判断是否已经加到结果里，如果没有才添加，如果已添加则跳过
    const dataType = node.dataset.type
    if (blockTypes.includes(dataType)) {
      if (!addedBlockIds.includes(blockId)) {
        addedBlockIds.push(blockId)
        result.push(node)
      }
      continue
    }

    // 2. 如果是章节、题条，则需要递归到下一个章或题条
    if (isListTitle(node.dataset.type)) {
      node.setAttribute('data-type', 'paragraph')
      node.removeAttribute('data-index')
      node.classList.remove('list-title')
      addedBlockIds.push(blockId)
      result.push(node)

      let endDataTypes = [...contentTypes]
      if (contentTypes.includes(dataType)) {
        getNextNodes(node, endDataTypes)
      } else if (dataType === 'item1') {
        getNextNodes(node, [...endDataTypes, 'item1'])
      } else if (dataType === 'item2') {
        getNextNodes(node, [...endDataTypes, 'item1', 'item2'])
      } else if (dataType === 'item3') {
        getNextNodes(node, [...endDataTypes, 'item1', 'item2', 'item3'])
      } else if (dataType === 'item4') {
        getNextNodes(node, [...endDataTypes, 'item1', 'item2', 'item3', 'item4'])
      }
    }
  }
  return result.reverse()
}

export function getRefHref(docNo) {
  if (!docNo) return ''
  return window.location.origin + '/editor/view?editContentType=document&entry=htmlpreview&docNo=' + docNo
}

export function checkDocInEdit() {
  let flag = true
  if (store.state.xmleditor.editorConfig.editContentType === 'document') {
    if (store.getters.entry) {
      console.warn('===预览不能保存===')
      flag = false
    }
    if (!store.state.xmleditor.canSave) {
      console.warn('===不是主编或没有权限===')
      flag = false
    }
  }
  return flag
}

export async function saveBeforeExport() {
  if (checkDocInEdit()) {
    await save(getStrData2Save())
  }
}

/** 计算当前节点所在的层级 */
export function getNearestListLevel(node) {
  if (!node) return 'Error'
  const { getPrev, is } = tinymce.activeEditor.dom
  if (is(node, '.list-title')) {
    return node.dataset.index
  }
  const prev = getPrev(node, '.list-title')
  if (prev) {
    return prev.dataset.index
  }

  return getNearestListLevel(node.parentNode)
}

export function updateDomain() {
  if (store.state.xmleditor.filePropertyName !== 'TERM') {
    return
  }
  const termsData = store.state.xmleditor.editorPageList.find((item) => item.dataType === 'terms_definitions')
  if (!termsData) return
  const termsArr =
    termsData?.children?.reduce(function fn(prev, cur) {
      if (!cur.children?.length) {
        prev.push(cur) // 只有最末级的节点才是术语 http://yunxiao.devops.comac.intra/issue/104029
      } else {
        cur.children.forEach((item) => fn(prev, item))
      }
      return prev
    }, []) || []

  const indexZh = termsArr.map((item) => {
    return {
      id: item.dataId,
      type: 'bizIndex',
      content: item.title,
      contentNumber: item.dataIndex
    }
  })
  const indexEn = termsArr
    .filter((item) => {
      const arr = item.titleZh?.trim()?.split(/\s+/g)
      const [_, ...items] = arr
      if (items.join('')?.length) {
        item.titleEn = items.join(' ')
        return item
      }
      return false
    })
    .map((item) => {
      return {
        id: item.dataId,
        type: 'bizIndexEn',
        content: item.titleEn,
        contentNumber: item.dataIndex
      }
    })

  store.commit('xmleditor/SET_INDEX_NODES', [indexZh, indexEn])
}

export function inTermBlock(node) {
  return tinymce.activeEditor.dom.getParent(node, '[data-type="terms"]')
}

/** 自动解析出章标题或条标题中的英文 */
export function parseFullContent(str) {
  let content = str
  let contentEn = ''
  if (store.getters.languageType !== 'both') {
    return { content, contentEn }
  }
  if (/[（]+/g.test(str) && /）$/g.test(str)) {
    const pos = str.indexOf('（')
    if (pos > -1) {
      content = str.slice(0, pos)
      contentEn = str.slice(pos + 1, str.length - 1)
    } else {
      console.warn('===没有匹配的英文名: 中文括号===')
    }
  } else if (/[\\(]+/g.test(str) && /\)$/g.test(str)) {
    const pos = str.indexOf('(')
    if (pos > -1) {
      content = str.slice(0, pos)
      contentEn = str.slice(pos + 1, str.length - 1)
    } else {
      console.warn('===没有匹配的英文名：英文括号===')
    }
  } else {
    console.warn('===没有匹配的英文名===', str.slice(0, 5) + '...')
  }

  return {
    content,
    contentEn
  }
}

function changePageList(listA, listB, allPageIdList) {
  for (let i = 0; i < allPageIdList.length; i++) {
    const pageId = allPageIdList[i]
    const posA = listA.findIndex((o) => o.pageId === pageId)
    const posB = listB.findIndex((o) => o.pageId === pageId)
    if (posA === -1) {
      const objB = listB.find((o) => o.pageId === pageId)

      listA.splice(i, 0, {
        ...objB,
        blockList: [{ dataType: 'blank_page' }]
      })
    }
    if (posB === -1) {
      const objA = listA.find((o) => o.pageId === pageId)
      listB.splice(i, 0, {
        ...objA,
        blockList: [{ dataType: 'blank_page' }]
      })
    }
  }

  return [listA, listB]
}

// 两侧页面高度对齐
export function alignCompareList(currentPageList, historyPageList) {
  const currentList = cloneDeep(currentPageList)
  const historyList = cloneDeep(historyPageList)
  const currentPageIdList = currentList.map((i) => i.pageId)
  const historyPageIdList = historyList.map((i) => i.pageId)
  const diff1 = difference(currentPageIdList, historyPageIdList)
  const diff2 = difference(historyPageIdList, currentPageIdList)
  const allPageIdList = cloneDeep(currentPageIdList)
  for (let i = 0; i < historyPageIdList.length; i++) {
    const item = historyPageIdList[i]
    if (allPageIdList.includes(item)) {
      continue
    } else {
      if (i === 0) {
        allPageIdList.unshift(item)
      } else {
        const pos = allPageIdList.indexOf(historyPageIdList[i - 1])
        allPageIdList.splice(pos + 1, 0, item)
      }
    }
  }

  return [...changePageList(currentList, historyList, allPageIdList), diff1, diff2, allPageIdList]
}

// 2.1.1 => 2.1.2, 2.2
export function getNextIndexList(indexStr) {
  const res = []
  const digits = indexStr.split('.').map(i => parseInt(i))
  for (let i = digits.length - 1; i > 0; i--) {
    const arr =digits.slice(0, i)
    arr.push(digits[i] + 1)
    res.push(arr.join('.'))
  }
  return res
}

export function getCopyedData(data) {
  if (data === null) return null
  const clonedData = cloneDeep(data)
  for (const key in clonedData) {
    if (Object.prototype.hasOwnProperty.call(clonedData, key)) {
      const ele = clonedData[key];
      if(['pageId', 'dataId', 'blockId'].includes(key)) {
        clonedData[key] = uuid()
      } else if (typeof ele === 'object' && ele !== null) {
        clonedData[key] = getCopyedData(ele)
      } else if (Array.isArray(ele)) {
        clonedData[key] = ele.map(item => {
          return getCopyedData(item)
        })
      }
    }
  }

  return clonedData
}
